package com.zlll.winner.service.activity;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zlll.winner.business.model.activity.ActivityApply;
import com.zlll.winner.business.model.activity.ActivityApplyExternal;
import com.zlll.winner.business.model.activity.ActivityManagement;
import com.zlll.winner.business.service.activity.IActivityApplyExternalService;
import com.zlll.winner.business.service.area.IAreaCityService;
import com.zlll.winner.business.vo.activity.ApplyInfoVo;
import com.zlll.winner.config.RedisLockWithIntegration;
import com.zlll.winner.mapper.activity.ActivityApplyMapper;
import com.zlll.winner.business.service.activity.IActivityApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlll.winner.mapper.activity.ActivityManagementMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;

/**
 * <p>
 * 活动申请管理 服务实现类
 * </p>
 *
 * @author qsx
 * @since 2019-09-16
 */
@Service
public class ActivityApplyServiceImpl extends ServiceImpl<ActivityApplyMapper, ActivityApply> implements IActivityApplyService {

    @Autowired
    private ActivityApplyMapper applyMapper;
    @Autowired
    private ActivityManagementMapper managementMapper;

    @Autowired
    private IAreaCityService areaCityService;

    @Autowired
    private IActivityApplyExternalService externalService;

    @Autowired
    private RedisLockWithIntegration redisLockWithIntegration;


    @Override
    public IPage<ActivityApply> getActivityApplyByActivityId(Long activityId, String cityCode, String name, String telphone, Long startTime, Long endTime, Integer pageNo, Integer pageSize) {
        IPage<ActivityApply> page = new Page<ActivityApply>(pageNo, pageSize);
        LambdaQueryWrapper<ActivityApply> applyLambdaQueryWrapper = Wrappers.lambdaQuery();
        applyLambdaQueryWrapper.eq(ActivityApply::getIsDel, 0);
        applyLambdaQueryWrapper.eq(ActivityApply::getActivityId, activityId);
        if (null != name && !name.equals("")) {
            applyLambdaQueryWrapper.like(ActivityApply::getName, name);
        }

        if (null != telphone && !telphone.equals("")) {
            applyLambdaQueryWrapper.like(ActivityApply::getTelphone, telphone);
        }
        if (null != startTime) {
            applyLambdaQueryWrapper.gt(ActivityApply::getCreateTime, startTime);
        }

        if (null != endTime) {
            applyLambdaQueryWrapper.lt(ActivityApply::getCreateTime, endTime);
        }
        if (null != cityCode && !cityCode.equals("")) {
            applyLambdaQueryWrapper.like(ActivityApply::getCityCode, cityCode);
        }
        return applyMapper.selectPage(page, applyLambdaQueryWrapper);
    }

    @Override
    public Boolean updateStatus(Long id, Integer status, Long userId) {
        Long time = System.currentTimeMillis();
        ActivityApply apply = applyMapper.selectById(id);
        apply.setUpdateUser(userId + "");
        apply.setStatus(status);
        apply.setUpdateTime(time);

        ActivityManagement activityManagement = managementMapper.selectById(apply.getActivityId());
        if (status == 0) {
            activityManagement.setApplyNum(activityManagement.getApplyNum() - apply.getNum());
        } else {
            activityManagement.setApplyNum(activityManagement.getApplyNum() + apply.getNum());

        }
        activityManagement.setUpdateUser(userId + "");
        activityManagement.setUpdateTime(time);
        managementMapper.updateById(activityManagement);
        return updateById(apply);
    }

    @Override
    public ActivityManagement updateActivityApply(Long id, String name, String telphone, Integer num, String externalInfo, Long userId) {
        Long time = System.currentTimeMillis();
        ActivityApply apply = applyMapper.selectById(id);
        apply.setName(name);
        apply.setTelphone(telphone);
        apply.setExternalInfo(externalInfo);
        Integer oldNum = apply.getNum();
        apply.setUpdateUser(userId + "");
        apply.setUpdateTime(time);
        apply.setNum(num);


        ActivityManagement activityManagement = managementMapper.selectById(apply.getActivityId());
        if (apply.getStatus().equals(1)) {
            activityManagement.setApplyNum(activityManagement.getApplyNum() - oldNum + num);
            activityManagement.setUpdateUser(userId + "");
            activityManagement.setUpdateTime(time);
            managementMapper.updateById(activityManagement);
        }
//        Long fee = Long.parseLong(num.toString()) * activityManagement.getFee();
        apply.setFee(activityManagement.getFee());
        updateById(apply);

        return activityManagement;
    }

    @Override
    public ActivityApply saveApply(ActivityApply activityApply) throws Exception {
        LambdaQueryWrapper<ActivityApply> applyLambdaQueryWrapper = Wrappers.lambdaQuery();
        applyLambdaQueryWrapper.eq(ActivityApply::getActivityId, activityApply.getActivityId());
        applyLambdaQueryWrapper.eq(ActivityApply::getIsDel, 0);
        applyLambdaQueryWrapper.eq(ActivityApply::getUserId, activityApply.getUserId());
        List<ActivityApply> activityApplies = applyMapper.selectList(applyLambdaQueryWrapper);
        if (activityApplies.size() > 0) {
            throw new Exception("你已报名过本次活动");
        }

        Lock lock = redisLockWithIntegration.getLock("Activity:" + activityApply.getActivityId(), 5, true);
        if (lock == null) {
            throw new Exception("活动报名过多");

        } else {
            long time = System.currentTimeMillis();
            activityApply.setCreateTime(time);
            activityApply.setApplyTime(time);
            ActivityManagement management = managementMapper.selectById(activityApply.getActivityId());

            if (management.getMaxPeopleNum() != null) {
                if (management.getMaxPeopleNum() != null && management.getMaxPeopleNum().equals(management.getApplyNum())) {
                    throw new Exception("报名人数到达上限人数");
                }
                Integer applyNum = management.getApplyNum() + activityApply.getNum();
                if (applyNum > management.getMaxPeopleNum()) {
                    throw new Exception("报名人数超过上限人数，剩余报名数为:" + (management.getMaxPeopleNum() - management.getApplyNum()));
                }
            }

            String cityCode = areaCityService.getCityCode(activityApply.getCityName());
            if (cityCode != null) {
                activityApply.setCityCode(cityCode);
            }
            management.setApplyNum(management.getApplyNum() + activityApply.getNum());
            management.setUpdateTime(time);
            applyMapper.insert(activityApply);
            managementMapper.updateById(management);
            lock.unlock();
            return activityApply;
        }
    }

    @Override
    public IPage<ApplyInfoVo> getApplyByUserId(Long userId, Integer pageNo, Integer pageSize) {
        IPage<ApplyInfoVo> page = new Page<ApplyInfoVo>(pageNo, pageSize);
        List<ApplyInfoVo> list = applyMapper.getApplyListByUserId(userId, page);

        for (ApplyInfoVo vo : list) {
            Long activityId = vo.getId();
            List<ActivityApplyExternal> externals = externalService.getExternalByActivityId(activityId);
             JSONObject jsonObject =JSONObject.parseObject(vo.getExternalInfo());

            if (externals.size() > 0) {
                List<Map<String,Object>> externalList = new ArrayList<>();
                for (ActivityApplyExternal external : externals) {
                    Map map = new HashMap();
                    map.put("name",external.getName());
                    map.put("code",external.getCode());
                    if(jsonObject.get(external.getCode()) != null) {
                        map.put("value", jsonObject.get(external.getCode()));
                        externalList.add(map);
                    }
                }

                vo.setExternalList(externalList);
            }
        }
        page.setRecords(list);
        return page;
    }


}
